package com.cxm.report.service.impl;

import com.cxm.report.dao.BrandReportDao;
import com.cxm.report.model.IReport;
import com.cxm.report.model.criteria.ReportFilter;
import com.cxm.report.model.data.BrandReport;
import com.cxm.report.model.data.ChannelReport;
import com.cxm.report.model.data.Report;
import com.cxm.report.model.data.ReportDetail;
import com.cxm.report.model.event.MailEvent;
import com.cxm.report.service.BrandReportService;
import com.cxm.report.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author scl.BlueOcean
 * @version 1.0
 * @date 2018年07月02 18:14
 * @description
 */
@Service
public class BrandReportServiceImpl extends AbstractReportService implements BrandReportService {
    @Autowired
    private BrandReportDao brandReportDao;

    @Override
    public List<Report> dayReport(ReportFilter filter) {
        List<BrandReport>  reportList = brandReportDao.selectReports(filter);
        return getReports(reportList,null);
    }

    private Report generateReport(List<Report> reports, String date, List<BrandReport> details) {
        Report report = new Report();
        report.setDate(date);
        report.setDetails(details);

        BrandReport total = caculateTotal(details);
        report.setTotal(total);
        reports.add(report);
        return report;
    }

    @Override
    public List<Report> timeScopeReport(ReportFilter filter) {
        List<Report> reports = new ArrayList<>();
        List<BrandReport>  reportList = brandReportDao.selectReportsOfScope(filter);
        generateReport(reports,String.format("%s～%s",filter.getBegin(),filter.getEnd()),reportList);
        return reports;
    }

    @Override
    public List<Report> monthReport(ReportFilter filter) {
        Report lastReport = getLastReport(filter.getBegin(),IReport.ScopeType.MONTH);
        List<BrandReport>  reportList = brandReportDao.selectReportsGroupMonth(filter);
        List<Report> reports = getReports(reportList, lastReport);
        //将最后一个移除
        Collections.reverse(reports);
        return reports;
    }


    @Override
    public List<Report> weekReport(ReportFilter filter) {
        Report lastReport = getLastReport(filter.getBegin(),IReport.ScopeType.WEEK);
        List<BrandReport>  reportList = brandReportDao.selectReportsGroupWeek(filter);
        List<Report> reports = getReports(reportList, lastReport);
        Collections.reverse(reports);
        setFirstAndLast(reports,filter);
        return reports;
    }

    private List<Report> getReports(List<BrandReport> reportList,Report lastReport) {
        List<Report> reports = new ArrayList<>();
        //按照日期进行分组
        Map<String, List<BrandReport>> reportMap = reportList.stream().collect(Collectors.groupingBy(BrandReport::getReportDate, LinkedHashMap::new,Collectors.toList()));

        for (Map.Entry<String, List<BrandReport>> detailMap: reportMap.entrySet()) {
            Report report = generateReport(reports, detailMap.getKey(), detailMap.getValue());
            setRingRatio(lastReport,report);
            lastReport = report;
        }
        return reports;
    }
    /**
     * 设置环比
     * @param lastReport
     * @param report
     */
    private void setRingRatio(Report lastReport,Report report){
        //如果上期的报告为不为null
        if (lastReport != null){
            List<BrandReport> lastReports = (List<BrandReport>) lastReport.getDetails();
            Map<String, BrandReport> lastReportsMap = lastReports.stream().collect(Collectors.toMap(BrandReport::getBrandName, b->b,(k1, k2)->k1));

            List<BrandReport> reports = (List<BrandReport>) report.getDetails();
            for (BrandReport brandReport : reports) {
                BrandReport last = lastReportsMap.get(brandReport.getBrandName());
                setRingRatio(brandReport, last);
            }
            setRingRatio((ReportDetail)report.getTotal(),(ReportDetail)lastReport.getTotal());
        }
    }


    /**
     * 生成上期报告
     * @param scopeType
     * @return
     */
    private Report getLastReport(String date, String scopeType) {
        try {
            ReportFilter filter = new ReportFilter();
            switch (scopeType){
                case IReport.ScopeType.MONTH:{
                    String[] monthScope = DateUtil.getLastMonthScope(date);
                    filter.setBegin(monthScope[0]);
                    filter.setEnd(monthScope[1]);
                    List<BrandReport>  reportList = brandReportDao.selectReportsGroupMonth(filter);
                    List<Report> reports = getReports(reportList, null);
                    return reports.get(0);
                }
                case IReport.ScopeType.WEEK:{
                    date = date.split("To")[0].trim();
                    String[] weekScope = DateUtil.getLastWeekScope(date);
                    filter.setBegin(weekScope[0]);
                    filter.setEnd(weekScope[1]);
                    List<BrandReport>  reportList = brandReportDao.selectReportsGroupWeek(filter);
                    List<Report> reports = getReports(reportList, null);
                    return reports.get(0);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 计算合计
     * @param details
     * @return
     */
    private BrandReport caculateTotal(List<BrandReport> details) {
        BrandReport total = details.stream().reduce(new BrandReport(),(x, y)->{
            x.setOrderNum(x.getOrderNum()+y.getOrderNum());
            x.setNoRecordNum(x.getNoRecordNum()+y.getNoRecordNum());
            x.setSuccessNum(x.getSuccessNum()+y.getSuccessNum());
            x.setOverTimeNum(x.getOverTimeNum()+y.getOverTimeNum());
            x.setInquiryNum(x.getInquiryNum()+y.getInquiryNum());
            x.setFailedNum(x.getFailedNum()+y.getFailedNum());
            x.setAvgQueryTime(x.getAvgQueryTime()+y.getSuccessNum()*y.getAvgQueryTime());
            return x;
        });
        total.setAvgQueryTime(total.getAvgQueryTime()/total.getSuccessNum());
        return total;

    }

    /**
     * 刷新数据
     * @param date
     */
    @Override
    public void refreshData(String date) {
        brandReportDao.delete(date);
        brandReportDao.insertBrandInfo(date);
        brandReportDao.updateBrandName(date);
        brandReportDao.updateSuccessNum(date);
        brandReportDao.updateFailedNum(date);
        brandReportDao.updateNoRecordNum(date);
        brandReportDao.updateOverTimeNum(date);
        brandReportDao.updateInquiryNum(date);
    }

    /*@Async
    void generateReport(String date) {
        date = getDefaultDate(date);
        Report report = new Report();
        report.setType(IReport.Type.BRAND);
        report.setDate(date);
        List<BrandReport> details = brandReportDao.selectReport(date);
        BrandReport total = caculateTotal(details);
        report.setTotal(total);
        report.setDetails(details);
        applicationContext.publishEvent(new MailEvent(report));
    }*/

    private String getDefaultDate(String date) {
        if (!StringUtils.hasText(date)){
            date = DateUtil.currentDay();
        }
        return date;
    }
}
